#include <stdio.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>

#include "main.h"
#include "user_login.h" // 用户登录

pthread_mutex_t keep_lock;
// 设计设备链表节点

struct device *head = NULL;
int client_socket = 0;

commodity_list_p commodity_head = NULL;

// 创建节点
struct device *create_node(char *device_name, int socket)
{
    // 创建设备节点
    struct device *new_node = (struct device *)malloc(sizeof(struct device));
    // 初始化设备节点
    strcpy(new_node->device_name, device_name);
    new_node->socket = socket;
    new_node->next = NULL;

    return new_node;
}

// 插入节点
void insert_device(struct device *head, struct device *new_node)
{
    struct device *pos = head;
    while (pos->next != NULL) // 偏移到末尾
    {
        pos = pos->next;
    }
    // 插入
    pos->next = new_node;
}

// 显示在线设备
void show_online_device(struct device *head)
{
    printf("____________当前在线设备_____________\n");

    struct device *pos = head->next;
    while (pos != NULL)
    {
        // 获取当前socket 的IP和端口
        struct sockaddr_in addr;
        int addrlen = sizeof(addr);
        getpeername(pos->socket, (struct sockaddr *)&addr, &addrlen);

        char *ip = inet_ntoa(addr.sin_addr);
        int port = ntohs(addr.sin_port);

        printf("设备名称：%s,socket:%d ip:%s port:%d\n", pos->device_name, pos->socket, ip, port);
        pos = pos->next;
    }
}

// 超时未注册
void reg_out(int arg)
{

    printf("设备超时未注册，断开连接\n");
    close(client_socket);
}

// 线程任务函数
// 读取设备信息
void *device_thread(void *arg)
{
    struct device *pos = (struct device *)arg;
    while (1)
    {
        char buf[1024] = {0};
        int size = read(pos->socket, buf, sizeof(buf));
        if (size <= 0)
        {
            printf("%s 设备断开连接\n", pos->device_name);
            // 从链表中删除该节点
            struct device *p = head;
            struct device *prev = NULL;
            while (p != NULL)
            {
                if (p == pos)
                {
                    if (prev == NULL)
                    {
                        head = p->next;
                    }
                    else
                    {
                        prev->next = p->next;
                    }
                    free(p);
                    break;
                }
                prev = p;
                p = p->next;
            }
            printf("设备断开连接\n");
            // 关闭socket
            close(pos->socket);
            pthread_exit(NULL);
            break;
        }
        if (strstr(buf, "login")) // 判断是否为登录
        {

            printf("开始登录!!!!\n");
            if (USER_LGOIN(buf) == 1) // 用户登录
            {

                printf("用户登录成功\n");
            }
            else
            {
                printf("用户登录失败\n");
            }
        }

        if (strstr(buf, "order")) // 判断是否为订单
        {
            // 开始处理订单
            printf("开始处理订单!!!!\n");
            int set = ORDER_RDWR(buf); // 处理订单
            if (set == 0)
            {
                printf("交易成功\n");
            }
        }

        if (strstr(buf, "go_on"))
        {
            write_go_on(buf);
            go_on(buf);
            COMMODITY_LIST_show_list(commodity_head);
            take_off_sand("1001"); // 发送商品信息
        }

        if (strstr(buf, "go_file"))
        {
            char h[128] = {0};
            char dev[128] = {0};
            char file[2048] = {0};
            char tcp_buf[1024] = {0};
            char *p1 = strtok(buf, ",");
            int i = 0;
            while (p1 != NULL)
            {
                printf("p1 = %s\n", p1);
                if (i == 1)
                    strcpy(h, p1);
                else if (i == 2)
                    strcpy(dev, p1);
                i++;
                p1 = strtok(NULL, ",");
            }
            // sprintf(file, "touch /root/kkcode/second_item/Data/commodity_picture/%s", dev);
            // system(file);
            sprintf(tcp_buf, "go_file,%s", dev);
            sleep(2);
            my_sand(tcp_buf, "1001");
            tcp_file(dev, h, pos);
        }

        if (strstr(buf, "take_off"))
        {
            take_off(buf);
            COMMODITY_LIST_show_list(commodity_head);

            take_off_sand("1001"); // 发送商品信息
        }
        if (strstr(buf, "get_comm"))
        {
            char h[128] = {0};
            char dev[128] = {0};
            char *p1 = strtok(buf, ",");
            int i = 0;
            while (p1 != NULL)
            {
                printf("p1 = %s\n", p1);
                if (i == 0)
                    strcpy(h, p1);
                else if (i == 1)
                    strcpy(dev, p1);
                i++;
                p1 = strtok(NULL, ",");
            }
            get_comm(dev);
        }
        // 商品当前信息转给user
        if (strstr(buf, "get_new")) // 判断是否为商品
        {
            printf("开始处理商品!!!!\n");
            // pthread_mutex_lock(&keep_lock); // 加锁
            char h[128] = {0};
            char dev[128] = {0};
            char *p1 = strtok(buf, ",");
            int i = 0;
            while (p1 != NULL)
            {
                printf("p1 = %s\n", p1);
                if (i == 0)
                    strcpy(h, p1);
                else if (i == 1)
                    strcpy(dev, p1);
                i++;
                p1 = strtok(NULL, ",");
            }
            get_new(dev);
            // pthread_mutex_unlock(&keep_lock); // 解锁
        }

        if (strstr(buf, "chat")) // chat,iphone,hello
        {
            printf("开始转发!!!!\n");

            // 找到转发的设备   chat iphone hello
            char h[128] = {0};
            char dev[128] = {0};
            char msg[256] = {0};

            char *p1 = strtok(buf, ",");
            int i = 0;
            while (p1 != NULL)
            {

                printf("p1 = %s\n", p1);
                if (i == 0)
                    strcpy(h, p1);
                else if (i == 1)
                    strcpy(dev, p1);
                else if (i == 2)
                    strcpy(msg, p1);

                i++;
                p1 = strtok(NULL, ",");
            }

            // 从链表中找到转发的设备
            struct device *p = head;
            while (p != NULL)
            {
                if (strstr(p->device_name, dev)) // 找到设备
                {
                    printf("找到%s设备%d,开始转发\n", p->device_name, p->socket);
                    // 发送数据
                    int size = write(p->socket, msg, strlen(msg));
                    printf("hao:%d\n", p->socket);
                    printf("发送的数据大小 %d\n", size);
                    break;
                }

                p = p->next;
            }
        }
    }

    // 关闭socket
    close(pos->socket);

    // 从链表中删除该节点
    pthread_exit(NULL);
}

// 主函数
int main(int argc, char const *argv[])
{
    pthread_mutex_init(&keep_lock, NULL);
    // 1.创建一个头节点
    head = (struct device *)malloc(sizeof(struct device));
    head->next = NULL;
    // 2.创建一个TCP服务器
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    // 开启端口复用功能
    int on = 1;
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    // 3.绑定IP和端口
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8899);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind fail:");
        return -1;
    }
    // 4.监听
    if (listen(server_socket, 10) < 0)
    {
        perror("listen fail:");
        return -1;
    }
    COMMODITY_LIST_Init(&commodity_head);
    COMMODITY_LIST_Update(commodity_head);
    COMMODITY_LIST_show_list(commodity_head);
    while (1)
    {
        // 5.接受客户端连接
        printf("等待设备注册\n");
        client_socket = accept(server_socket, NULL, NULL);
        if (client_socket < 0)
        {
            perror("accept fail:");
            continue;
        }
        // 6.接收设备注册名称
        printf("新设备.....\n");
        char device_name[50] = {0};
        int ret = read(client_socket, device_name, 50);
        if (ret <= 0)
        {
            perror("设备注册失败\n");
            close(client_socket);
            continue;
        }

        // reg 设备名  <-  协议  reg 协议头 设备名 协议信息
        if (strstr(device_name, "reg"))
        {
            printf("设备注册成功\n");

            // 7.将设备信息保存到设备链表中 ,&device_name[4] 去掉 reg 头部
            struct device *xnew = create_node(&device_name[4], client_socket);
            insert_device(head, xnew);

            // 8.开启一个线程,处理该设备的消息
            pthread_t tid;
            pthread_create(&tid, NULL, device_thread, (void *)xnew);
            pthread_t keep_id;
            pthread_create(&keep_id, NULL, keep, (void *)xnew);
        }
        else
        {
            printf("设备注册失败\n");
            close(client_socket);
        }

        // 9. 显示当前在线的设备
        show_online_device(head);
    }

    return 0;
}
